/**
 * 
 */
package br.com.ufrn.aipetro.ga.view.form;

import java.beans.PropertyChangeEvent;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Tab;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import br.com.ufrn.aipetro.ga.controller.device.ControllerController;
import br.com.ufrn.aipetro.ga.domain.entity.device.Critical;
import br.com.ufrn.aipetro.ga.domain.entity.device.OperationStatus;
import br.com.ufrn.aipetro.ga.domain.entity.device.Protocol;
import br.com.ufrn.aipetro.ga.domain.entity.mesh.Mesh;
import br.com.ufrn.aipetro.ga.domain.entity.plant.Plant;
import br.com.ufrn.aipetro.ga.domain.entity.stock.Part;
import br.com.ufrn.aipetro.ga.domain.entity.unit.Unit;
import br.com.ufrn.aipetro.ga.model.persist.hibernate.HibernateDaoFactory;
import br.com.ufrn.aipetro.ga.view.interfaces.View;

/**
 * @author Andre
 * 
 */
public class FormControllerFxmlController implements View<ControllerController>, Initializable {

	private static final int INSERT_MODE = 0;
	private static final int UPDATE_MODE = 1;

	private int editMode;
	private ControllerController controller;

	@FXML private AnchorPane root;
	@FXML private Tab parent;
	@FXML private TextField tfdDeviceId;
	@FXML private TextField tfdSerialNumber;
	@FXML private TextField tfdManufacturer;
	@FXML private TextField tfdModel;
	@FXML private TextField tfdTag;
	@FXML private ComboBox<Protocol> cbbProtocol;
	@FXML private ComboBox<OperationStatus> cbbOperationStatus;
	@FXML private ComboBox<Unit> cbbUnit;
	@FXML private ComboBox<Plant> cbbPlant;
	@FXML private ComboBox<Mesh> cbbMesh;
	@FXML private ComboBox<Critical> cbbCritical;
	@FXML private CheckBox ckbAutomaticMode;
	@FXML private TextField tfdMv;
	@FXML private TextField tfdMvMin;
	@FXML private TextField tfdMvMax;
	@FXML private TextField tfdPv;
	@FXML private TextField tfdSp;
	@FXML private TextField tfdSpMin;
	@FXML private TextField tfdSpMax;
	@FXML private TextField tfdSearchPartParam;
	@FXML private TableView<Part> tbvResultSearchPart;
	@FXML private TableColumn<Part, String> tbcResultSearchPartDescription;
	@FXML private TableColumn<Part, String> tbcResultSearchPartManufacturer;
	@FXML private TableColumn<Part, String> tbcResultSearchPartModel;
	private ObservableList<Part> tbvResultSearchPartData;
	@FXML private TableView<Part> tbvPart; 
	@FXML private TableColumn<Part, String> tbcPartDescription;
	@FXML private TableColumn<Part, String> tbcPartManufacturer;
	@FXML private TableColumn<Part, String> tbcPartModel;
	private ObservableList<Part> tbvPartData;

	public FormControllerFxmlController() {
		editMode = INSERT_MODE;
		initView(new ControllerController(new HibernateDaoFactory()));
	}

	@FXML
	public void cancelForm() {
	}
	
	@FXML
	private void close() {
	}
	
	/**
	 * 
	 */
	private void configureTbvResultSearchPart() {
		tbcResultSearchPartDescription.setCellValueFactory(new PropertyValueFactory<Part,String>("description"));
    	tbcResultSearchPartManufacturer.setCellValueFactory(new PropertyValueFactory<Part,String>("manufacturer"));
    	tbcResultSearchPartModel.setCellValueFactory(new PropertyValueFactory<Part,String>("model"));
    	
    	tbvResultSearchPartData = FXCollections.observableArrayList();
    	tbvResultSearchPart.setItems(tbvResultSearchPartData);
	}
	
	private void configureTbvPart() {
		tbcPartDescription.setCellValueFactory(new PropertyValueFactory<Part,String>("description"));
    	tbcPartManufacturer.setCellValueFactory(new PropertyValueFactory<Part,String>("manufacturer"));
    	tbcPartModel.setCellValueFactory(new PropertyValueFactory<Part,String>("model"));
    	
    	tbvPartData = FXCollections.observableArrayList();
    	tbvPart.setItems(tbvPartData);
	}

	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
		loadCbbOperationStatus();
		loadCbbProtocol();
		loadCbbUnit();
		loadCbbCritical();
		configureTbvResultSearchPart();
		configureTbvPart();
	}
	
	@Override
	public void initView(ControllerController controller) {
		this.controller = controller;
		this.controller.registerView(this);
	}

	private void insertController() {
		loadFormToController();
		controller.persistInsert();
		setUpdateMode();
	}
	
	/**
	 * Povoa o combo box com a lista das Malhas disponiveis 
	 */
	private void loadCbbMesh() {
		cbbMesh.getItems().clear();
		cbbMesh.getItems().addAll(controller.persistSearchMeshByPlant((cbbPlant.getSelectionModel().getSelectedItem())));
	}
	
	/**
	 * Povoa o combo box com a lista dos status de operacao disponiveis 
	 */
	private void loadCbbOperationStatus() {
		cbbOperationStatus.getItems().clear();
		cbbOperationStatus.getItems().addAll(controller.persistSearchAllOperationStatus());
	}
	
	/**
	 * Povoa o combo box com a lista dos niveis criticos disponiveis 
	 */
	private void loadCbbCritical() {
		cbbCritical.getItems().clear();
		cbbCritical.getItems().addAll(controller.persistSearchAllCritical());
	}
	
	/**
	 * Povoa o combo box com a lista das Plantas disponiveis 
	 */
	private void loadCbbPlant() {
		cbbPlant.getItems().clear();
		cbbPlant.getItems().addAll(controller.persistSearchPlantByUnit(cbbUnit.getSelectionModel().getSelectedItem()));
	}
	
	/**
	 * Povoa o combo box com a lista dos protocolos disponiveis 
	 */
	private void loadCbbProtocol() {
		cbbProtocol.getItems().clear();
		cbbProtocol.getItems().addAll(controller.persistSearchAllProtocol());
	}
	
	/**
	 * Povoa o combo box com a lista das unidades disponiveis 
	 */
	private void loadCbbUnit() {
		cbbUnit.getItems().clear();
		cbbUnit.getItems().addAll(controller.persistSearchAllUnit());
	}
	
	private void loadControllerToForm() {
		this.tfdDeviceId.setText(controller.getModel().getDeviceId());
		this.tfdSerialNumber.setText(controller.getModel().getSerialNumber());
		this.tfdManufacturer.setText(controller.getModel().getManufacturer());
		this.tfdModel.setText(controller.getModel().getModel());
		this.tfdTag.setText(controller.getModel().getTag());
		this.cbbOperationStatus.getSelectionModel().select(controller.getModel().getOperationStatus());
		this.cbbProtocol.getSelectionModel().select(controller.getModel().getProtocol());
		this.cbbUnit.getSelectionModel().select(controller.getModel().getMesh().getPlant().getUnit());
		this.cbbPlant.getSelectionModel().select(controller.getModel().getMesh().getPlant());
		this.cbbMesh.getSelectionModel().select(controller.getModel().getMesh());
		this.ckbAutomaticMode.setSelected(controller.getModel().isAutomaticMode());
		this.tfdMv.setText(String.valueOf(controller.getModel().getMv()));
		this.tfdMvMin.setText(String.valueOf(controller.getModel().getMvMin()));
		this.tfdMvMax.setText(String.valueOf(controller.getModel().getMvMax()));
		this.tfdPv.setText(String.valueOf(controller.getModel().getPv()));
		this.tfdSp.setText(String.valueOf(controller.getModel().getSp()));
		this.tfdSpMin.setText(String.valueOf(controller.getModel().getSpMin()));
		this.tfdSpMax.setText(String.valueOf(controller.getModel().getSpMax()));
	}
	
	private void loadFormToController() {
		controller.changeDeviceId(this.tfdDeviceId.getText());
		controller.changeSerialNumber(this.tfdSerialNumber.getText());
		controller.changeManufacturer(this.tfdManufacturer.getText());
		controller.changeModel(this.tfdModel.getText());
		controller.changeTag(this.tfdTag.getText());
		controller.changeOperationStatus(this.cbbOperationStatus.getSelectionModel().getSelectedItem());
		controller.changeProtocol(this.cbbProtocol.getSelectionModel().getSelectedItem());
		controller.changeMesh(this.cbbMesh.getSelectionModel().getSelectedItem());
		controller.changeDeviceId(this.tfdDeviceId.getText());
		controller.changeAutomaticMode(this.ckbAutomaticMode.isSelected());
		controller.changeMv(Float.valueOf(tfdMv.getText()));
		controller.changeMvMin(Float.valueOf(tfdMvMin.getText()));
		controller.changeMvMax(Float.valueOf(tfdMvMax.getText()));
		controller.changePv(Float.valueOf(tfdPv.getText()));
		controller.changeSp(Float.valueOf(tfdSp.getText()));
		controller.changeSpMin(Float.valueOf(tfdSpMin.getText()));
		controller.changeSpMax(Float.valueOf(tfdSpMax.getText()));
	}
	
	private void loadTbvPart() {
		tbvPart.getItems().addAll(controller.getModel().getPartList());
	}
	
	@Override
	public void propertyChange(PropertyChangeEvent evt) {
//		if (evt.getPropertyName().equals(Unit.NAME_PROPERTY))
//			tfdUnitName.setText((String) evt.getNewValue());
	}
	
	@FXML
	public void saveForm() {
		if (this.editMode == INSERT_MODE)
			insertController();
		else
			updateController();
		
	}
	
	@FXML
	public void selectPlant() {
		loadCbbMesh();
	}
	
	@FXML
	public void selectUnit() {
		loadCbbPlant();
	}
	
	private void updateController() {
		loadFormToController();
		controller.persistUpdate();
	}

	@Override
	public void modelChange() {
		setUpdateMode();
		loadControllerToForm();
	}
	
	@FXML
	public void addPartToDevice() {
		Part part = tbvResultSearchPart.getSelectionModel().getSelectedItem();
		tbvPart.getItems().add(part);
		controller.addPartToDevice(part);
	}
	
	@FXML
	public void removePartToDevice() {
		Part part = tbvPart.getSelectionModel().getSelectedItem();
		tbvPart.getItems().remove(part);
		controller.removePartFromDevice(part);
	}
	
	@FXML
	public void searchPart() {
		Part partExample = new Part();
		partExample.setDescription(tfdSearchPartParam.getText());
		System.out.println(partExample.getDescription());
		List<Part> partList = controller.persistSearchPartByExample(partExample);
		tbvResultSearchPart.getItems().clear();
		tbvResultSearchPart.getItems().addAll(partList);
	}
	
	private void setUpdateMode() {
		this.editMode = UPDATE_MODE;
		loadTbvPart();
	}

}
